﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.Mvc;

namespace StarterKits.Mvc.Filters.FormsAuthentication
{
	public abstract class BaseAuthenticationAttribute : ActionFilterAttribute
	{

		private FailureResponse _OnFailure = FailureResponse.HttpStatus;
		public FailureResponse OnFailure
		{
			get { return _OnFailure; }
			set { _OnFailure = value; }
		}

		public enum FailureResponse
		{
			HttpStatus,
			ThrowException,
			RedirectToLogin
		}

		protected void HandleFailure( ActionExecutingContext filterContext )
		{
			if( OnFailure == FailureResponse.ThrowException )
			{
				throw new UnauthorizedAccessException();
			}
			else if( OnFailure == FailureResponse.HttpStatus )
			{

				//### as suggested in: http://www.codeplex.com/MvcMembership/WorkItem/View.aspx?WorkItemId=311
				//### 401 code added in response to: http://www.codeplex.com/MvcMembership/WorkItem/View.aspx?WorkItemId=338
				if( filterContext.HttpContext.User.Identity.IsAuthenticated )
				{
					filterContext.HttpContext.Response.StatusCode = 403;
					filterContext.HttpContext.Response.StatusDescription = "Forbidden";
				}
				else
				{
					filterContext.HttpContext.Response.StatusCode = 401;
					filterContext.HttpContext.Response.StatusDescription = "Unauthorized";
				}
				filterContext.Cancel = true;

			}
			else
			{

				//use the current url for the redirect
				string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;

				//send them off to the login page
				string redirectUrl = string.Format( "?ReturnUrl={0}", redirectOnSuccess );
				string loginUrl = System.Web.Security.FormsAuthentication.LoginUrl + redirectUrl;
				filterContext.HttpContext.Response.Redirect( loginUrl, true );

			}
		}

		public override void OnActionExecuting( ActionExecutingContext filterContext )
		{
			if( !IsValid(filterContext) )
				HandleFailure( filterContext );
		}

		protected abstract bool IsValid( ActionExecutingContext filterContext );

	}
}
